package cn.eonshine.cuba.inf.modular.infMapping.controller;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import cn.eonshine.base.core.base.controller.BaseController;
import cn.eonshine.base.core.base.tips.SuccessTip;
import cn.eonshine.base.core.common.constant.factory.PageFactory;
import cn.eonshine.base.core.common.exception.BizExceptionEnum;
import cn.eonshine.base.core.exception.GunsException;
import cn.eonshine.base.core.support.HttpKit;
import cn.eonshine.base.core.util.ClazzUtils;
import cn.eonshine.base.core.util.LocaleStringUtil;
import cn.eonshine.base.core.util.ToolUtil;
import cn.eonshine.cuba.inf.common.http.InfStatus;
import cn.eonshine.cuba.inf.common.http.Message;
import cn.eonshine.cuba.inf.modular.basic.entity.Mapping;
import cn.eonshine.cuba.inf.modular.common.IMappingCommon;
import cn.eonshine.cuba.inf.modular.security.server.IKeyService;
import cn.eonshine.cuba.inf.modular.sys.entity.Dict;
import cn.eonshine.cuba.inf.modular.sys.service.IDictService;
import cn.eonshine.cuba.lsms.modular.basic.entity.InfMapping;
import cn.eonshine.cuba.lsms.modular.basic.entity.Office;
import cn.eonshine.cuba.lsms.modular.basic.entity.OilInfo;
import cn.eonshine.cuba.lsms.modular.basic.entity.OilTankInfo;
import cn.eonshine.cuba.lsms.modular.basic.entity.Port;
import cn.eonshine.cuba.lsms.modular.basic.service.IOfficeService;
import cn.eonshine.cuba.lsms.modular.basic.service.IOilInfoService;
import cn.eonshine.cuba.lsms.modular.basic.service.IOilTankInfoService;
import cn.eonshine.cuba.lsms.modular.basic.service.IPortService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.EscapeUtil;
import cn.hutool.json.JSONUtil;

/**
 * 控制器
 *z
 * @author fengshuonan
 * @Date 2018-10-26 10:46:06
 */
@Controller
@RequestMapping({"/infMapping","/rest/infMapping"})
public class InfMappingController extends BaseController {

    private String PREFIX = "/infMapping/";
    @Autowired
	private IKeyService keyService;
    @Autowired
    private IDictService dictService;
    @Autowired
    private IOilTankInfoService oilTankService;

    @RequestMapping("")
    public String index(Model model) {
    	List<Dict> subDicts = getDictList();
    	model.addAttribute("dataTypeLists",subDicts);
    	
        return PREFIX + "infMapping.html";
    }
    
    @RequestMapping("/getDataTypeList")
    @ResponseBody
    public List<Dict> getDictList(){
    	Dict dataType = dictService.getOne(new QueryWrapper<Dict>().eq("name", InfStatus.DICT_DATA_TYPE_NAME));
    	List<Dict> subDicts = Lists.newArrayList();
    	if(dataType != null) {
    		subDicts = dictService.list(new QueryWrapper<Dict>().eq("pid", dataType.getId()));
    	}
    	return subDicts;
    }

    @RequestMapping("/infMapping_add")
    public String infMappingAdd(Model model) {
    	Dict dataType = dictService.getOne(new QueryWrapper<Dict>().eq("name", InfStatus.DICT_DATA_TYPE_NAME));
    	List<Dict> subDicts = Lists.newArrayList();
    	if(dataType != null) {
    		subDicts = dictService.list(new QueryWrapper<Dict>().eq("pid", dataType.getId()));
    	}
    	model.addAttribute("dataTypeLists",subDicts);
    	
    	InfMapping infMapping = new InfMapping();
		infMapping.setDataType(InfStatus.DMZ_MAPPING_OIL_DEPOT);
		IPage<Mapping> page = getMappingInfos(infMapping);
		model.addAttribute("depots",page.getRecords());
    	
        return PREFIX + "infMapping_add.html";
    }
    
    @RequestMapping("/infMapping_update/{infMappingId}")
    public String infMappingUpdate(@PathVariable("infMappingId") String infMappingId, Model model) {
    	if (ToolUtil.isEmpty(infMappingId)) {
    		throw new GunsException(BizExceptionEnum.REQUEST_NULL);
    	}
    	InfMapping infMap= infMappingUpdateById(infMappingId, model);
        model.addAttribute("infMap",infMap);
        return PREFIX + "infMapping_edit.html";
    }
    
    @RequestMapping("/getInfMapping/{infMappingId}")
    @ResponseBody
    public InfMapping infMappingUpdateById(@PathVariable("infMappingId") String infMappingId, Model model) {
    	String urlRoot = keyService.getServerHttpRoot();
    	Message message = keyService.clientRequestDataList(urlRoot+"/mapping/detail/"+infMappingId, JSONUtil.toJsonStr(infMappingId));
    	InfMapping infMap=new InfMapping();
    	if(message.getStatus() == InfStatus.INF_OK && message.getCount()>0) {
    		Mapping  map=JSONUtil.toBean(message.getMsg(), Mapping.class);
    		infMap.setLsmsId(map.getLsmsId());
    		infMap.setId(map.getId());
    		infMap.setDmz1(EscapeUtil.safeUnescape(map.getDmz1()));
    		if(StringUtils.isNotBlank(map.getDmz2())) {
    			infMap.setDmz2(EscapeUtil.safeUnescape(map.getDmz2()));
    		}
    		infMap.setDmz8(EscapeUtil.safeUnescape(map.getDmz8()));
    		infMap.setName(EscapeUtil.safeUnescape(map.getName()));
    		infMap.setDataType(map.getDataType());
    		
    		if(StringUtils.isNotBlank(map.getCreateBy())) {
    			infMap.setCreateBy(map.getCreateBy());
    		}
    		if(map.getCreateDate() != null) {
    			infMap.setCreateDate(map.getCreateDate());
    		}
    		if(StringUtils.isNotBlank(map.getUpdateBy())) {
    			infMap.setUpdateBy(map.getUpdateBy());
    		}
    		if(map.getUpdateDate() != null) {
    			infMap.setUpdateDate(map.getUpdateDate());
    		}
    		
    		if(map.getDataType().equals(InfStatus.DMZ_MAPPING_OIL_TANKER)) {
    			InfMapping infMapping = new InfMapping();
    			infMapping.setDataType(InfStatus.DMZ_MAPPING_OIL_DEPOT);
    			IPage<Mapping> page = getMappingInfos(infMapping);
    			model.addAttribute("depots",page.getRecords());
    		}
    	}
    	return infMap;
    }

    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(InfMapping infMapping, Model model) {
    	Page<Mapping> page = getMappingInfos(infMapping);
    	if(!page.getRecords().isEmpty()) {
    		List<Dict> subDicts = getDictList();
    		Map<String, Dict> subDictMaps =  Maps.uniqueIndex(subDicts, new Function<Dict, String>() {
				@Override
				public @Nullable String apply(@Nullable Dict dict) {
					return dict.getNum().toString();
				}
    		});

    		List<Mapping> list = page.getRecords();
    		for (Mapping mapping : list) {
    			String key  = mapping.getDataType();
				if(subDictMaps.containsKey(key)) {
					mapping.setDataType(subDictMaps.get(key).getName());
				}
			}
    	}
    	
    	return  packForBT(page);
    }
    
    private Page<Mapping> getMappingInfos(InfMapping infMapping){
    	String urlRoot = keyService.getServerHttpRoot();
    	Map<String, Object> transMap = Maps.newHashMap();
    	HttpServletRequest request = HttpKit.getRequest();
    	transMap.put(IMappingCommon.SORT, request.getParameter("sort"));
    	transMap.put(IMappingCommon.ORDER, request.getParameter("order"));
    	
    	Page<Mapping> page = null;
    	if(StringUtils.isNoneBlank(request.getParameter("limit"))) {
    		page=new PageFactory<Mapping>().defaultPage();
    	}else {
    		page = new Page<Mapping>(0, 500);
    	}
    	Map<String,Object> map= BeanUtil.beanToMap(infMapping, false, true);
    	map = ClazzUtils.convertBeanFieldToDBField(map, InfMapping.class);
    	//page.setCondition(map);
    	transMap.put(IMappingCommon.PAGE_KEY, page);
    	transMap.put(IMappingCommon.CONDITION_KEY, map);
    	
    	Message message = keyService.clientRequestDataList(urlRoot+"/mapping/list", JSONUtil.toJsonStr(transMap));
    	if(message.getStatus() == InfStatus.INF_OK && message.getCount()>0) {
//    		page=JSONUtil.toBean(JSONUtil.parseObj(message.getMsg()), Page.class);
    		ObjectMapper mapper = new ObjectMapper();
    		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    		try {
				page =  mapper.readValue(message.getMsg() ,new TypeReference<Page<Mapping>>(){});
			} catch (Exception e) {
				e.printStackTrace();
			}
    	}
    	return page;
    }

    @RequestMapping(value = "/add")
    @ResponseBody
    public Object add(InfMapping infMapping) {
    	List<Mapping> list=Lists.newArrayList();
    	Mapping map=new Mapping();
    	map.setDmz1(EscapeUtil.safeUnescape(infMapping.getDmz1()));
    	map.setLsmsId(infMapping.getLsmsId());
    	map.setDmz8(EscapeUtil.safeUnescape(infMapping.getDmz8()));
    	if(StringUtils.isNotBlank(infMapping.getDmz2())) {
    		map.setDmz2(EscapeUtil.safeUnescape(infMapping.getDmz2()));
    	}
    	map.setName(EscapeUtil.safeUnescape(infMapping.getName()));
    	map.setDataType(infMapping.getDataType());
    	if(StringUtils.isNotBlank(infMapping.getId())) {
    		map.setId(infMapping.getId());
    	}
    	
    	map = createUserInfo(map, infMapping);
    	
    	list.add(map);
    	SUCCESS_TIP = addMappingHandle(list);
    	return SUCCESS_TIP;
    }
    
    private SuccessTip addMappingHandle(List<Mapping> list) {
    	String urlRoot = keyService.getServerHttpRoot();
    	String addUrl = urlRoot+"/mapping/add";
    	Message changeLsmsFlag = keyService.clientRequestDataList(addUrl, JSONUtil.toJsonStr(list));
    	if(changeLsmsFlag.getStatus()==InfStatus.INF_ERROR) {
    		SUCCESS_TIP.setCode(InfStatus.INF_ERROR);
    		SUCCESS_TIP.setMessage(LocaleStringUtil.getMessage("save.failed"));
    	}else {
    		if(changeLsmsFlag.getFlag()==InfStatus.SAVE_STATUS_FAIELD) {
    			SUCCESS_TIP.setCode(InfStatus.SAVE_STATUS_FAIELD);
        		SUCCESS_TIP.setMessage(LocaleStringUtil.getMessage("save.failed"));
    		}else if(changeLsmsFlag.getFlag()==InfStatus.SAVE_STATUS_SUCESS) {
    			SUCCESS_TIP.setCode(InfStatus.SAVE_STATUS_SUCESS);
        		SUCCESS_TIP.setMessage(LocaleStringUtil.getMessage("save.successful"));
    		}else {
    			SUCCESS_TIP.setCode(InfStatus.SAVE_STATUS_EXCEPTION);
        		SUCCESS_TIP.setMessage(changeLsmsFlag.getMsg());
    		}
    	}
    	return SUCCESS_TIP;
    }

    @RequestMapping(value = "/delete")
    @ResponseBody
    public Object delete(@RequestParam String infMappingId) {
    	 if (ToolUtil.isEmpty(infMappingId)) {
             throw new GunsException(BizExceptionEnum.REQUEST_NULL);
         }
	   	String urlRoot = keyService.getServerHttpRoot();
	   	Message changeLsmsFlag = keyService.clientRequestDataList(urlRoot+"/mapping/delete/"+infMappingId, JSONUtil.toJsonStr(infMappingId));
        
	   	if(changeLsmsFlag.getStatus()==InfStatus.INF_ERROR) {
    		SUCCESS_TIP.setCode(InfStatus.INF_ERROR);
    		SUCCESS_TIP.setMessage(LocaleStringUtil.getMessage("save.failed"));
    	}else {
    		if(changeLsmsFlag.getFlag()==InfStatus.SAVE_STATUS_FAIELD) {
    			SUCCESS_TIP.setCode(InfStatus.SAVE_STATUS_FAIELD);
        		SUCCESS_TIP.setMessage(LocaleStringUtil.getMessage("save.failed"));
    		}else if(changeLsmsFlag.getFlag()==InfStatus.SAVE_STATUS_SUCESS) {
    			SUCCESS_TIP.setCode(InfStatus.SAVE_STATUS_SUCESS);
        		SUCCESS_TIP.setMessage(LocaleStringUtil.getMessage("save.successful"));
    		}else {
    			SUCCESS_TIP.setCode(InfStatus.SAVE_STATUS_EXCEPTION);
        		SUCCESS_TIP.setMessage(changeLsmsFlag.getMsg());
    		}
    	}
    	return SUCCESS_TIP;
    }

    @RequestMapping(value = "/update")
    @ResponseBody
    public Object update(InfMapping infMapping) {
    	add(infMapping);
        return SUCCESS_TIP;
    }

    @Autowired
    private IOfficeService officeService;
    @Autowired
    private IOilInfoService oilInfoService;
    @Autowired
    private IPortService portService;
    
    @RequestMapping(value = "/sync")
    @ResponseBody
    public Object syncMapping() {
    	HttpServletRequest request = HttpKit.getRequest();
    	String updateBy = request.getParameter("updateBy");
    	QueryWrapper<Office> officeQuery = new QueryWrapper<Office>();
    	officeQuery.lambda().eq(Office::getDelFlag, InfStatus.LSMS_UPDATE_EXTRACT_YES);
    	List<Office> lists = officeService.list(officeQuery);
    	List<Mapping> listMapping=Lists.newArrayList();
    	for (Office office : lists) {
    		Mapping map=new Mapping();
        	map.setLsmsId(office.getId());
        	map.setName(office.getName());
        	String mappingDataType="";
        	if(InfStatus.LSMS_OFFICE_TYPE.ORG_TYPE_ECC.equals(office.getType())) {
        		mappingDataType = InfStatus.DMZ_MAPPING_ECC;
        	}else if(InfStatus.LSMS_OFFICE_TYPE.ORG_TYPE_OILDEPOT.equals(office.getType())) {
        		mappingDataType = InfStatus.DMZ_MAPPING_OIL_DEPOT;
        	}else if(InfStatus.LSMS_OFFICE_TYPE.ORG_TYPE_REFINERY.equals(office.getType())) {
        		mappingDataType = InfStatus.DMZ_MAPPING_REFINERY;
        	}else if(InfStatus.LSMS_OFFICE_TYPE.ORG_TYPE_GAS_STATION.equals(office.getType())) {
        		mappingDataType = InfStatus.DMZ_MAPPING_OIL_STATION;
        	}else if(InfStatus.LSMS_OFFICE_TYPE.ORG_TYPE_OILFIELD.equals(office.getType())) {
        		mappingDataType = InfStatus.DMZ_MAPPING_OILFIELD;
        	}
        	map.setUpdateBy(updateBy);
        	if(StringUtils.isNotBlank(mappingDataType)) {
	        	map.setDataType(mappingDataType);
	        	listMapping.add(map);
        	}
		}
    	QueryWrapper<OilInfo> oilQuery = new QueryWrapper<OilInfo>();
    	oilQuery.lambda().eq(OilInfo::getDelFlag, InfStatus.LSMS_UPDATE_EXTRACT_YES);
    	List<OilInfo> oils = oilInfoService.list(oilQuery);
    	for (OilInfo oil : oils) {
    		Mapping map=new Mapping();
    		map.setLsmsId(oil.getId());
        	map.setName(oil.getOilName());
        	map.setDataType(InfStatus.DMZ_MAPPING_OIL);
        	map.setUpdateBy(updateBy);
        	listMapping.add(map);
		}
    	QueryWrapper<Port> portQuery = new QueryWrapper<Port>();
    	portQuery.lambda().eq(Port::getDelFlag, InfStatus.LSMS_UPDATE_EXTRACT_YES);
    	List<Port> ports = portService.list();
    	for (Port port : ports) {
    		Mapping map=new Mapping();
    		map.setLsmsId(port.getId());
        	map.setName(port.getName());
        	map.setDataType(InfStatus.DMZ_MAPPING_GPS_TANKER_PORT);
        	map.setUpdateBy(updateBy);
        	listMapping.add(map);
		}
    	QueryWrapper<Office> depotQuery = new QueryWrapper<Office>();
    	depotQuery.lambda().eq(Office::getType, InfStatus.LSMS_OFFICE_TYPE.ORG_TYPE_OILDEPOT);
    	depotQuery.lambda().eq(Office::getDelFlag, InfStatus.LSMS_UPDATE_EXTRACT_YES);
    	lists = officeService.list(depotQuery);
    	Map<String, Office> depotMaps = Maps.uniqueIndex(lists, new Function<Office, String>() {
			@Override
			public @Nullable String apply(@Nullable Office office) {
				return office.getId();
			}
		});
    	
    	QueryWrapper<OilTankInfo> oilTankQuery = new QueryWrapper<OilTankInfo>();
    	oilTankQuery.lambda().eq(OilTankInfo::getDelFlag, InfStatus.LSMS_UPDATE_EXTRACT_YES);
    	List<OilTankInfo> OilTankInfos = oilTankService.list(oilTankQuery);
    	for (OilTankInfo tank : OilTankInfos) {
    		Mapping map=new Mapping();
    		map.setLsmsId(tank.getId());
    		if(depotMaps.containsKey(tank.getOilDepotId())) {
	    		map.setName(depotMaps.get(tank.getOilDepotId()).getName()+" - "+tank.getOilTankName());
    		}
    		if(StringUtils.isNotBlank(tank.getOilTankCode())) {
    			map.setDmz8(tank.getOilTankCode());
    		}
    		map.setDataType(InfStatus.DMZ_MAPPING_OIL_TANKER);
    		map.setUpdateBy(updateBy);
    		listMapping.add(map);
		}
    	SUCCESS_TIP = addMappingHandle(listMapping);
    	return SUCCESS_TIP;
    }
    
    
    private Mapping createUserInfo(Mapping map, InfMapping infMapping) {
    	if(StringUtils.isNotBlank(infMapping.getCreateBy())) {
			map.setCreateBy(infMapping.getCreateBy());
		}
		if(infMapping.getCreateDate() != null) {
			map.setCreateDate(infMapping.getCreateDate());
		}
		if(StringUtils.isNotBlank(infMapping.getUpdateBy())) {
			map.setUpdateBy(infMapping.getUpdateBy());
		}
		if(infMapping.getUpdateDate() != null) {
			map.setUpdateDate(infMapping.getUpdateDate());
		}
		return map;
    }
}
